/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦，本文采用木兰宽松许可证第2版]
 * 
 * https://zhiqim.org/project/zhiqim_products/gitcan.htm
 *
 * gitcan is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.gitcan;

import java.util.HashMap;

import org.zhiqim.gitcan.dbo.GitIssue;
import org.zhiqim.httpd.HttpRequest;
import org.zhiqim.kernel.util.seqs.Sequence;
import org.zhiqim.orm.ORM;
import org.zhiqim.orm.ZTable;
import org.zhiqim.orm.dbo.Selector;

/**
 * 问题序号项目内自增
 *
 * @version v1.0.0 @author zouzhigang 2017-11-7 新建与整理
 */
public class GitIssueSequence
{
    private static final HashMap<Long, Sequence> map = new HashMap<>();

    /**
     * 获取项目内的自增序号
     * 
     * @param projectId     项目编号
     * @return              下一个问题编号
     * @throws Exception    读数据库异常
     */
    public static int nextId(HttpRequest request, long projectId) throws Exception
    {
        Sequence seq = map.get(projectId);
        if (seq != null)
        {//同步外部检查，已存在返回结果
            return seq.nextInt();
        }
        
        synchronized (map)
        {
            seq = map.get(projectId);
            if (seq != null)
            {//同步内部检查，并发已存在返回结果
                return seq.nextInt();
            }
            
            Selector selector = new Selector("issueSeq");
            selector.addMust("projectId", projectId);
            selector.addOrderbyDesc("issueSeq");
            GitIssue item = ORM.get(ZTable.class, request).item(GitIssue.class, selector);
            
            long min = (item == null)?1:item.getIssueSeq()+1;
            seq = new Sequence(min, Integer.MAX_VALUE);
            map.put(projectId, seq);
            
            return seq.nextInt();
        }
    }
}
